/*
 * Created by Gibbs on 2021/1/1.
 * Copyright (c) 2021 Gibbs. All rights reserved.
 */

#include <base/LoopThread.h>
#include <render/SurfaceVideoRenderer.h>
#include <base/XTick.h>
#include <render/Renderer.h>
#include "RenderHelper.h"

RenderHelper::RenderHelper(FrameSource *frameSource, MessageSource *messageSource, int mediaCodecFlag) {
    this->mediaCodecFlag = mediaCodecFlag;
    if (frameSource->containAudio()) {
        audioRenderer = new AudioRenderer(frameSource);
    }
    if (frameSource->containVideo()) {
        if (mediaCodecFlag) {
            videoRenderer = new SurfaceVideoRenderer(frameSource);
        } else {
            videoRenderer = new YuvVideoRenderer(frameSource);
        }
    }
    avSyncMethod = frameSource->containAudio() ? FELLOW_AUDIO : FELLOW_CLOCK;
    this->messageSource = messageSource;
    isEof = false;
}

RenderHelper::~RenderHelper() {
    delete audioRenderer;
    delete videoRenderer;
}

void RenderHelper::setNativeWindow(ANativeWindow *window) {
    nativeWindow = window;
}

void RenderHelper::setAudioTrack(AudioTrackJni *track) {
    audioRenderer->setAudioTrack(track);
}

void RenderHelper::setVideoParams(int width, int height) {
    videoWidth = width;
    videoHeight = height;
}

void RenderHelper::setAudioParams(int sampleRate, int channels, int format, int bytesPerSample) {
    audioRenderer->setAudioParams(sampleRate, channels, format, bytesPerSample);
}

void RenderHelper::initAudioRenderer() {
    audioRenderer->init();
    hasNotifyFirstFrame = false;
    isEof = false;
}

void RenderHelper::initVideoRenderer() {
    videoRenderer->surfaceCreated(nativeWindow, videoWidth, videoHeight);
    hasNotifyFirstFrame = false;
    isEof = false;
    startPts = getTickCount64();
}

int RenderHelper::renderAudio(int arg1, long arg2) {
    int64_t temp = audioRenderer->render(nowPts);
    if (temp == RENDER_ERROR) {
        LOGI("RenderHelper", "the audio queue is quit");
        return ERROR_EXIST;
    } else if (temp == RENDER_RETRY) {
        return 0;
    } else if (temp == RENDER_END && !isEof) {
        LOGI("RenderHelper", "the audio queue is end");
        isEof = true;
        messageSource->pushMessage(MSG_DOMAIN_COMPLETE, 0, 0);
        return ERROR_EXIST;
    }
    if (!hasNotifyFirstFrame) {
        hasNotifyFirstFrame = true;
        messageSource->pushMessage(MSG_DOMAIN_STATE, STATE_STARTED, 0);
    }
    nowPts = temp;
    int nowPtsSecond = nowPts / 1000 / 1000;
    messageSource->pushMessage(MSG_DOMAIN_TIME, nowPtsSecond, 0);
    return 0;
}

int RenderHelper::renderVideo(int arg1, long arg2) {
    if (!videoRenderer->isRenderValid()) {
        return ERROR_EXIST;
    }
    int64_t temp;
    if (avSyncMethod == FELLOW_CLOCK) {
        nowPts = (getTickCount64() - startPts) * 1000 + firstFramePts;
        int nowPtsSecond = nowPts / 1000 / 1000;
        messageSource->pushMessage(MSG_DOMAIN_TIME, nowPtsSecond, 0);
        //确保第一帧快速被渲染
        temp = videoRenderer->render(firstFramePts != 0 ? nowPts : MAX_PTS);
    } else {
        temp = videoRenderer->render(nowPts);
    }
    if (temp == RENDER_ERROR) {
        LOGI("RenderHelper", "the video queue is quit");
        return ERROR_EXIST;
    } else if (temp == RENDER_RETRY) {
        return 0;
    } else if (temp == RENDER_END && !isEof) {
        LOGI("RenderHelper", "the video queue is end");
        isEof = true;
        messageSource->pushMessage(MSG_DOMAIN_COMPLETE, 0, 0);
        return ERROR_EXIST;
    }
    if (!hasNotifyFirstFrame) {
        firstFramePts = temp;
        hasNotifyFirstFrame = true;
        messageSource->pushMessage(MSG_DOMAIN_STATE, STATE_STARTED, 0);
    }
    return 0;
}

void RenderHelper::releaseAudioRenderer() {
    audioRenderer->release();
}

void RenderHelper::releaseVideoRenderer() {
    videoRenderer->surfaceDestroyed();
}
